/************************************
*  Copyright (C) 2010 Julien MOTTIN.
*  Contact: julien.mottin@gueydan.eu
*
*  This file is part of Gueydan.
*
*  Gueydan is free software: you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation, either version 3 of the License, or
*  (at your option) any later version.
*
*  Gueydan is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with Gueydan.  If not, see <http://www.gnu.org/licenses/>.
*
*************************************/
// Local
#include "water.h"
#include "xmldico.h"
#include "util.h"
#include "beerxmlobject.h"

// QtCore
#include <QtGlobal>

// QtXml
#include <QDomNode>
#include <QDomElement>
#include <QDomDocument>
#include <QDomNodeList>
#include <QDomText>

Water::Water(const QString &iName,
             int iVersion,
             const Volume &iAmount,
             float iCalcium,
             float iBicarbonate,
             float iSulfate,
             float iChloride,
             float iSodium,
             float iMagnesium)
:BeerXMLObject(iName,iVersion)
,_Amount(iAmount)
,_Calcium(iCalcium)
,_Bicarbonate(iBicarbonate)
,_Sulfate(iSulfate)
,_Chloride(iChloride)
,_Sodium(iSodium)
,_Magnesium(iMagnesium)
,_PH(0.0)
,_Notes()
{
}

Water::Water()
:BeerXMLObject()
,_Amount(0.0)
,_Calcium(0.0)
,_Bicarbonate(0.0)
,_Sulfate(0.0)
,_Chloride(0.0)
,_Sodium(0.0)
,_Magnesium(0.0)
,_PH(0.0)
,_Notes()
{
}

Water::~Water()
{
}

bool Water::operator==(const Water &iOther) const
{
    return ((*this).BeerXMLObject::operator==(iOther) &&
            _Amount == iOther._Amount &&
            ComparePrecision(_Calcium,iOther._Calcium) &&
            ComparePrecision(_Bicarbonate,iOther._Bicarbonate) &&
            ComparePrecision(_Sulfate,iOther._Sulfate) &&
            ComparePrecision(_Chloride,iOther._Chloride) &&
            ComparePrecision(_Sodium,iOther._Sodium) &&
            ComparePrecision(_Magnesium,iOther._Magnesium) &&
            ComparePrecision(_PH,iOther._PH,0.01) &&
            _Notes == iOther._Notes);
}

bool Water::operator!=(const Water &iOther) const
{
    return (!((*this)==iOther));
}

int Water::CreateFromXMLNode(const QDomNode &iNode)
{
    int oRC = 1;
    if (!iNode.isNull())
    {
        QDomElement WaterElement;

        // Case Document : check if doc has only one Hop element
        if (iNode.isDocument())
        {
            QDomDocument WaterDoc = iNode.toDocument();
            QDomNodeList WaterList = WaterDoc.elementsByTagName(WATER);
            if (WaterList.length()==1)
                WaterElement = WaterList.item(0).toElement();
        }
        // Default : cast to element
        else
            WaterElement = iNode.toElement();

        // Check element consistency
        if (!WaterElement.isNull() && WATER==WaterElement.tagName())
        {
            // Check existence of mandatory elements
            bool WaterName = false;
            bool WaterVersion = false;
            bool WaterAmount = true;
            bool WaterCalcium = true;
            bool WaterBicarbonate = true;
            bool WaterSulfate = true;
            bool WaterChloride = true;
            bool WaterSodium = true;
            bool WaterMagnesium = true;
            QDomNode node = WaterElement.firstChild();
            while (!node.isNull())
            {
                if (node.isElement())
                {
                    QDomElement elem = node.toElement();
                    QString name = elem.tagName();
                    QString text = elem.text();
                    if (name==WATER_NAME)
                    {
                        _Name = text;
                        WaterName = true;
                    }
                    else if (name==WATER_VERSION)
                    {
                        bool ok = false;
                        int v = text.toInt(&ok);
                        if (ok)
                        {
                            _Version = v;
                            WaterVersion = true;
                        }
                    }
                    else if (name==WATER_AMOUNT)
                    {
                        bool ok = false;
                        _Amount.FromString(text,&ok);
                        if (ok)
                            WaterAmount = true;
                    }
                    else if (name==WATER_CALCIUM)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                        {
                            _Calcium = v;
                            WaterCalcium = true;
                        }
                    }
                    else if (name==WATER_BICARBONATE)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                        {
                            _Bicarbonate = v;
                            WaterBicarbonate = true;
                        }
                    }
                    else if (name==WATER_SULFATE)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                        {
                            _Sulfate = v;
                            WaterSulfate = true;
                        }
                    }
                    else if (name==WATER_CHLORIDE)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                        {
                            _Chloride = v;
                            WaterChloride = true;
                        }
                    }
                    else if (name==WATER_SODIUM)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                        {
                            _Sodium = v;
                            WaterSodium = true;
                        }
                    }
                    else if (name==WATER_MAGNESIUM)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                        {
                            _Magnesium = v;
                            WaterMagnesium = true;
                        }
                    }
                    else if (name==WATER_PH)
                    {
                        bool ok = false;
                        float v = text.toFloat(&ok);
                        if (ok)
                        {
                            _PH = v;
                        }
                    }
                    else if (name==WATER_NOTES)
                    {
                        _Notes = text;
                    }
                }

                // Iterate
                node = node.nextSibling();
            }

            // Update output
            if (WaterName && WaterVersion && WaterCalcium && WaterBicarbonate && WaterSulfate && WaterChloride && WaterSodium && WaterMagnesium)
            {
                oRC = 0;
            }
        }
    }
    return oRC;
}

int Water::ToXMLNode(QDomNode &iParentNode) const
{
    int oRC = 1;

    // First, create valid element node
    QDomDocument doc = iParentNode.ownerDocument();
    QDomElement WaterNode = doc.createElement(WATER);
    if (!WaterNode.isNull())
    {
        if (!_Name.isEmpty() && _Version>0)
        {
            QDomElement node;
            QDomText textNode;

            // Name
            node = doc.createElement(WATER_NAME);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(_Name);
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            WaterNode.appendChild(node);

            // Version
            node = doc.createElement(WATER_VERSION);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_Version));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            WaterNode.appendChild(node);

            // Amount
            node = doc.createElement(WATER_AMOUNT);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_Amount.Value(Liter)));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            WaterNode.appendChild(node);

            // Calcium
            node = doc.createElement(WATER_CALCIUM);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_Calcium));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            WaterNode.appendChild(node);

            // Bicarbonate
            node = doc.createElement(WATER_BICARBONATE);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_Bicarbonate));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            WaterNode.appendChild(node);

            // Sulfate
            node = doc.createElement(WATER_SULFATE);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_Sulfate));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            WaterNode.appendChild(node);

            // Chloride
            node = doc.createElement(WATER_CHLORIDE);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_Chloride));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            WaterNode.appendChild(node);

            // Sodium
            node = doc.createElement(WATER_SODIUM);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_Sodium));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            WaterNode.appendChild(node);

            // Magnesium
            node = doc.createElement(WATER_MAGNESIUM);
            Q_ASSERT(!node.isNull());
            textNode = doc.createTextNode(QString::number(_Magnesium));
            Q_ASSERT(!textNode.isNull());
            node.appendChild(textNode);
            WaterNode.appendChild(node);

            // PH
            if (_PH>0)
            {
                node = doc.createElement(WATER_PH);
                Q_ASSERT(!node.isNull());
                textNode = doc.createTextNode(QString::number(_PH));
                Q_ASSERT(!textNode.isNull());
                node.appendChild(textNode);
                WaterNode.appendChild(node);
            }

            // Notes
            if (!_Notes.isEmpty())
            {
                node = doc.createElement(WATER_NOTES);
                Q_ASSERT(!node.isNull());
                textNode = doc.createTextNode(_Notes);
                Q_ASSERT(!textNode.isNull());
                node.appendChild(textNode);
                WaterNode.appendChild(node);
            }

            // Update output
            QDomNode zeNode = iParentNode.appendChild(WaterNode);
            if (!zeNode.isNull())
                oRC = 0;
        }
    }
    return oRC;
}
